"use strict";

const os = require("os");
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const {exec, execSync} = require("child_process")
const zipBuild = require("./zip-tools");

const isWin = process.platform === "win32";
const projectPath = Editor.Project.path || Editor.projectPath;
const pathShells = path.join(projectPath, "excel");
const encoding = isWin ? "utf-8" : "utf-8"

module.exports = {
    load() {
        // execute when package loaded
    },

    unload() {
        // execute when package unloaded
    },

    // register your ipc messages here
    messages: {
        "parseZip"() {
            this.parse((count) => {
                if (count > 0) {
                    this.zipTxt();
                } else {
                    Editor.log("无文件变更，不压缩文件");
                }
            });
        },
        "zipTxt"() {
            this.zipTxt();
        },
        "parse"() {
            this.parse();
        },

        "refreshDB"() {
            this.refreshDB();
        }
    },

    zipTxt() {
        const platform = os.platform();
        Editor.log("开始执行压缩配置文件脚本", platform);
        zipBuild(platform === "win32").then(() => {
            const dbPath = "db://assets/resources/zip";
            Editor.log("配置文件压缩完毕~,准备刷新目录", dbPath);
            Editor.assetdb.refresh(dbPath, (err, results) => {
                if (err) {
                    Editor.error("Failed to refresh zip %s", dbPath, err.stack);
                    return;
                }
                Editor.log("刷新zip目录完成");
            });
        }).catch((err) => {
            Editor.error("压缩配置文件脚本执行失败", err);
        })
    },
    parse(finishCallback) {
        let cmd = isWin ? "excel_to_json_windows_amd64.exe" : "excel_to_json_darwin_arm64";
        if (!isWin) {
            let cpus = os.cpus();
            if (cpus.length > 1) {
                if (cpus[0].model.toLowerCase().indexOf("intel") >= 0) {
                    cmd = "excel_to_json_darwin_amd64";
                }
            }
        }
        if (!isWin) cmd = path.join(pathShells, cmd);
        Editor.log("开始转换，执行命令:" + cmd);

        let md5BeforeParse = this.listMd5();

        exec(cmd,
            {cwd: pathShells, encoding: encoding},
            (error, stdout, stderr) => {
                if (error) {
                    Editor.log(`excel-cmd exec error:${error}`);
                    Editor.log(`excel-cmd exec stdout:${stdout}`);
                    let lines = stdout.split("\n");
                    if (lines.length > 0) {
                        let index = lines.length - 1;
                        let line = lines[index];
                        while (!line && index > 0) line = lines[--index];
                        Editor.log(`转换失败:${line}`);
                    } else {
                        Editor.log("转换失败");
                    }
                } else {
                    Editor.log(`excel-cmd exec stdout:${stdout}`);
                    Editor.log("转换完成");
                }

                let md5AfterParse = this.listMd5();
                this.refreshDBWithMd5(md5BeforeParse, md5AfterParse, finishCallback);
            }
        );
    },
    refreshDB() {
        Editor.log("开始刷新config目录");
        Editor.assetdb.refresh("db://assets/resources/config", (err, results) => {
            if (err) {
                Editor.error("Failed to reimport asset %s", err.stack);
                return;
            }
            Editor.log("刷新config目录完成");
            // Editor.assetdb._handleRefreshResults(results);
        });
    },

    refreshDBWithMd5(before, after, completeCallback) {
        Editor.log("开始刷新config目录");
        // Editor.log("before:" + JSON.stringify(before));
        // Editor.log("after:" + JSON.stringify(after));
        let count = 0;
        let refreshed = 0;
        for (let key in after) {
            if (before[key] === after[key]) {
                continue;
            }
            let dbPath = "db://assets/resources/config" + key;
            // Editor.log("开始刷新文件:" + dbPath);
            count++;
            Editor.assetdb.refresh(dbPath, (err, results) => {
                refreshed++;
                if (err) {
                    Editor.error("Failed to reimport asset %s, %s", dbPath, err.stack);
                    return;
                }
                results.forEach(function (result) {
                    Editor.log(`完成刷新文件：${dbPath} 结果：${result.command}`);
                });
                if (refreshed >= count) {
                    Editor.log("刷新config目录完成");
                } else {
                    // Editor.log("刷新文件完成：" + dbPath);
                }
                // Editor.assetdb._handleRefreshResults(results);
            });
        }
        if (count === 0) {
            Editor.log("无文件变更，不刷新config目录");
        } else {
            Editor.log("变更文件数量：" + count);
        }

        if (completeCallback) completeCallback(count);
    },

    listMd5() {
        let dir = path.join(projectPath, "assets", "resources", "config");
        return this._listMd5(dir, dir, {});
    },

    _listMd5(root, dir, ret) {
        let files = fs.readdirSync(dir);
        // Editor.log(`dir:${dir} file length:${files.length}`);
        const keyRoot = root.replaceAll("\\", "/");
        files.forEach(file => {
            let fullPath = path.join(dir, file);
            if (path.extname(file) === ".txt") {
                console.log(file);
                let buffer = fs.readFileSync(fullPath);
                let fsHash = crypto.createHash("md5");
                fsHash.update(buffer);
                let md5 = fsHash.digest("hex");
                crypto.createHash("md5")
                let key = fullPath.replaceAll("\\", "/").replace(keyRoot, '');
                ret[key] = md5;
                // Editor.log("key:" + key + " md5:" + md5);
            } else if (fs.lstatSync(fullPath).isDirectory()) {
                this._listMd5(root, fullPath, ret);
            }
        })
        return ret;
    }
};